package com.business.student.service.impl;


import com.business.common.core.domain.AjaxResult;
import com.business.common.utils.SecurityUtils;
import com.business.exam.domain.ExamPaperAnswer;
import com.business.exam.domain.ExamPaperAnswerInfo;
import com.business.exam.domain.ExamPaperModel;
import com.business.exam.domain.ExamPaperQuestionCustomerAnswer;
import com.business.exam.domain.enums.ExamPaperAnswerStatusEnum;
import com.business.exam.domain.enums.ExamPaperTypeEnum;
import com.business.exam.domain.enums.QuestionTypeEnum;
import com.business.exam.domain.exam.ExamPaperTitleItemObject;
import com.business.exam.domain.question.Question;
import com.business.exam.mapper.ExamPaperMapper;
import com.business.exam.mapper.QuestionMapper;
import com.business.exam.mapper.TextContentMapper;
import com.business.exam.utils.ExamUtil;
import com.business.exam.utils.JsonUtil;
import com.business.student.domain.ExamPaperAnswerPageVM;
import com.business.student.domain.ExamPaperSubmitItemVM;
import com.business.student.domain.ExamPaperSubmitVM;
import com.business.student.mapper.ExamPaperAnswerMapper;
import com.business.student.mapper.ExamPaperQuestionCustomerAnswerMapper;
import com.business.student.service.IExamPaperAnswerService;
import com.business.student.service.IExamPaperQuestionCustomerAnswerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ExamPaperAnswerServiceImpl implements IExamPaperAnswerService {


    @Autowired
    private ExamPaperMapper examPaperMapper;

    @Autowired
    private ExamPaperAnswerMapper examPaperAnswerMapper;

    @Autowired
    private ExamPaperQuestionCustomerAnswerMapper examPaperQuestionCustomerAnswerMapper;

    @Autowired
    private TextContentMapper textContentMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private IExamPaperQuestionCustomerAnswerService examPaperQuestionCustomerAnswerService;

    @Override
    public List<ExamPaperAnswer> studentPage(ExamPaperAnswerPageVM requestVM) {
        return  examPaperAnswerMapper.studentPage(requestVM);
    }

    @Override
    public ExamPaperAnswerInfo calculateExamPaperAnswer(ExamPaperSubmitVM examPaperSubmitVM) {
        ExamPaperAnswerInfo examPaperAnswerInfo = new ExamPaperAnswerInfo();
        Date now = new Date();
        ExamPaperModel examPaper = examPaperMapper.selectDataById(examPaperSubmitVM.getId());
        ExamPaperTypeEnum paperTypeEnum = ExamPaperTypeEnum.fromCode(Integer.parseInt(examPaper.getPaperType()));
        //任务试卷只能做一次
        if (paperTypeEnum == ExamPaperTypeEnum.Task) {
            ExamPaperAnswer examPaperAnswer = examPaperAnswerMapper.getByPidUid(examPaperSubmitVM.getId(), SecurityUtils.getUserId().intValue());
            if (null != examPaperAnswer)
                return null;
        }
        String frameTextContent = textContentMapper.selectByPrimaryKey(examPaper.getFrameTextContentId()).getContent();
        List<ExamPaperTitleItemObject> examPaperTitleItemObjects = JsonUtil.toJsonListObject(frameTextContent, ExamPaperTitleItemObject.class);
        List<Integer> questionIds = examPaperTitleItemObjects.stream().flatMap(t -> t.getQuestionItems().stream().map(q -> q.getId())).collect(Collectors.toList());
        List<Question> questions = questionMapper.selectByIds(questionIds);
        //将题目结构的转化为题目答案
        List<ExamPaperQuestionCustomerAnswer> examPaperQuestionCustomerAnswers = examPaperTitleItemObjects.stream()
                .flatMap(t -> t.getQuestionItems().stream()
                        .map(q -> {
                            Question question = questions.stream().filter(tq -> tq.getId().equals(q.getId())).findFirst().get();
                            ExamPaperSubmitItemVM customerQuestionAnswer = examPaperSubmitVM.getAnswerItems().stream()
                                    .filter(tq -> tq.getQuestionId().equals(q.getId()))
                                    .findFirst()
                                    .orElse(null);
                            return ExamPaperQuestionCustomerAnswerFromVM(question, customerQuestionAnswer, examPaper, q.getItemOrder(), now);
                        })
                ).collect(Collectors.toList());

        ExamPaperAnswer examPaperAnswer = ExamPaperAnswerFromVM(examPaperSubmitVM, examPaper, examPaperQuestionCustomerAnswers, now);
        examPaperAnswer.setExamMngId(examPaperSubmitVM.getExamMngId());

        // 保存考试记录表
        examPaperAnswerMapper.insertSelective(examPaperAnswer);

        examPaperAnswerInfo.setExamPaper(examPaper);
        examPaperAnswerInfo.setExamPaperAnswer(examPaperAnswer);
        examPaperAnswerInfo.setExamPaperQuestionCustomerAnswers(examPaperQuestionCustomerAnswers);

        // 保存人员选择答案
        examPaperQuestionCustomerAnswers.forEach(x->{
            x.setExamPaperAnswerId(examPaperAnswer.getId());
            examPaperQuestionCustomerAnswerMapper.insertSelective(x);
        });

        return examPaperAnswerInfo;
    }

    @Override
    public ExamPaperAnswer selectById(Integer id) {
        return examPaperAnswerMapper.selectByPrimaryKey(id);
    }

    @Override
    public ExamPaperSubmitVM  examPaperAnswerToVM(Integer id) {
        ExamPaperSubmitVM examPaperSubmitVM = new ExamPaperSubmitVM();
        ExamPaperAnswer examPaperAnswer = examPaperAnswerMapper.selectByPrimaryKey(id);
        examPaperSubmitVM.setId(examPaperAnswer.getId());
        examPaperSubmitVM.setDoTime(examPaperAnswer.getDoTime());
        examPaperSubmitVM.setScore(ExamUtil.scoreToVM(examPaperAnswer.getUserScore()));
        List<ExamPaperQuestionCustomerAnswer> examPaperQuestionCustomerAnswers = examPaperQuestionCustomerAnswerMapper.selectListByPaperAnswerId(examPaperAnswer.getId());
        List<ExamPaperSubmitItemVM> examPaperSubmitItemVMS = examPaperQuestionCustomerAnswers.stream()
                .map(a -> examPaperQuestionCustomerAnswerService.examPaperQuestionCustomerAnswerToVM(a))
                .collect(Collectors.toList());
        examPaperSubmitVM.setAnswerItems(examPaperSubmitItemVMS);
        return examPaperSubmitVM;
    }

    @Override
    public List<ExamPaperAnswer> studentPageForAdmin(ExamPaperAnswerPageVM requestVM) {
        return  examPaperAnswerMapper.studentPageForAdmin(requestVM);
    }

    @Override
    public AjaxResult findUserAnswerCount(String id) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userId", SecurityUtils.getUserId());
        paramMap.put("examMngId", id);
        int count = examPaperAnswerMapper.selectExamAnswerCount(paramMap);
        if(count>0){
            return AjaxResult.error("专项考试只能参加1次!");
        }
        return AjaxResult.success();
    }

    /**
     * 用户提交答案的转化存储对象
     *
     * @param question               question
     * @param customerQuestionAnswer customerQuestionAnswer
     * @param examPaper              examPaper
     * @param itemOrder              itemOrder
     * @param now                    now
     * @return ExamPaperQuestionCustomerAnswer
     */
    private ExamPaperQuestionCustomerAnswer ExamPaperQuestionCustomerAnswerFromVM(Question question, ExamPaperSubmitItemVM customerQuestionAnswer, ExamPaperModel examPaper, Integer itemOrder, Date now) {
        ExamPaperQuestionCustomerAnswer examPaperQuestionCustomerAnswer = new ExamPaperQuestionCustomerAnswer();
        examPaperQuestionCustomerAnswer.setQuestionId(question.getId());
        examPaperQuestionCustomerAnswer.setExamPaperId(examPaper.getId());
        examPaperQuestionCustomerAnswer.setQuestionScore(question.getScore());
        examPaperQuestionCustomerAnswer.setSubjectId(examPaper.getSubjectId());
        examPaperQuestionCustomerAnswer.setItemOrder(itemOrder);
        examPaperQuestionCustomerAnswer.setCreateTime(now);
        examPaperQuestionCustomerAnswer.setCreateUser(SecurityUtils.getUserId().intValue());
        examPaperQuestionCustomerAnswer.setQuestionType(question.getQuestionType());
        examPaperQuestionCustomerAnswer.setQuestionTextContentId(question.getInfoTextContentId());
        if (null == customerQuestionAnswer) {
            examPaperQuestionCustomerAnswer.setCustomerScore(0);
        } else {
            setSpecialFromVM(examPaperQuestionCustomerAnswer, question, customerQuestionAnswer);
        }
        return examPaperQuestionCustomerAnswer;
    }

    /**
     * 判断提交答案是否正确，保留用户提交的答案
     *
     * @param examPaperQuestionCustomerAnswer examPaperQuestionCustomerAnswer
     * @param question                        question
     * @param customerQuestionAnswer          customerQuestionAnswer
     */
    private void setSpecialFromVM(ExamPaperQuestionCustomerAnswer examPaperQuestionCustomerAnswer, Question question, ExamPaperSubmitItemVM customerQuestionAnswer) {
        QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.fromCode(examPaperQuestionCustomerAnswer.getQuestionType());
        switch (questionTypeEnum) {
            case SingleChoice:
            case TrueFalse:
                examPaperQuestionCustomerAnswer.setAnswer(customerQuestionAnswer.getContent());
                examPaperQuestionCustomerAnswer.setDoRight(question.getCorrect().equals(customerQuestionAnswer.getContent()));
                examPaperQuestionCustomerAnswer.setCustomerScore(examPaperQuestionCustomerAnswer.getDoRight() ? question.getScore() : 0);
                break;
            case MultipleChoice:
                String customerAnswer = ExamUtil.contentToString(customerQuestionAnswer.getContentArray());
                examPaperQuestionCustomerAnswer.setAnswer(customerAnswer);
                examPaperQuestionCustomerAnswer.setDoRight(customerAnswer.equals(question.getCorrect()));
                examPaperQuestionCustomerAnswer.setCustomerScore(examPaperQuestionCustomerAnswer.getDoRight() ? question.getScore() : 0);
                break;
            case GapFilling:
                String correctAnswer = JsonUtil.toJsonStr(customerQuestionAnswer.getContentArray());
                examPaperQuestionCustomerAnswer.setAnswer(correctAnswer);
                examPaperQuestionCustomerAnswer.setCustomerScore(0);
                break;
            default:
                examPaperQuestionCustomerAnswer.setAnswer(customerQuestionAnswer.getContent());
                examPaperQuestionCustomerAnswer.setCustomerScore(0);
                break;
        }
    }

    private ExamPaperAnswer ExamPaperAnswerFromVM(ExamPaperSubmitVM examPaperSubmitVM, ExamPaperModel examPaper, List<ExamPaperQuestionCustomerAnswer> examPaperQuestionCustomerAnswers, Date now) {
        Integer systemScore = examPaperQuestionCustomerAnswers.stream().mapToInt(a -> a.getCustomerScore()).sum();
        long questionCorrect = examPaperQuestionCustomerAnswers.stream().filter(a -> a.getCustomerScore().equals(a.getQuestionScore())).count();
        ExamPaperAnswer examPaperAnswer = new ExamPaperAnswer();
        examPaperAnswer.setPaperName(examPaper.getName());
        examPaperAnswer.setDoTime(examPaperSubmitVM.getDoTime());
        examPaperAnswer.setExamPaperId(examPaper.getId());
        examPaperAnswer.setCreateUser(SecurityUtils.getUserId().intValue());
        examPaperAnswer.setCreateTime(now);
        examPaperAnswer.setSubjectId(examPaper.getSubjectId());
        examPaperAnswer.setQuestionCount(examPaper.getQuestionCount());
        examPaperAnswer.setPaperScore(examPaper.getScore());
        examPaperAnswer.setPaperType(Integer.parseInt(examPaper.getPaperType()));
        examPaperAnswer.setSystemScore(systemScore);
        examPaperAnswer.setUserScore(systemScore);
        examPaperAnswer.setTaskExamId(examPaper.getTaskExamId());
        examPaperAnswer.setQuestionCorrect((int) questionCorrect);

        // 判断是否及格
        if (systemScore >= examPaper.getPassScore()) {
            examPaperAnswer.setPassStatus("1");
        } else {
            examPaperAnswer.setPassStatus("2");
        }

//        boolean needJudge = examPaperQuestionCustomerAnswers.stream().anyMatch(d -> QuestionTypeEnum.needSaveTextContent(d.getQuestionType()));
//        if (needJudge) {
//            examPaperAnswer.setStatus(ExamPaperAnswerStatusEnum.WaitJudge.getCode());
//        } else {
            examPaperAnswer.setStatus(ExamPaperAnswerStatusEnum.Complete.getCode());
//        }
        return examPaperAnswer;
    }


}
